// Copyright (c) 2022 CHANGLEI. All rights reserved.

import 'dart:math' as math;

import 'package:aircraft_war/components/enemy_aircraft.dart';
import 'package:flame/components.dart';
import 'package:flutter/foundation.dart' as foundation;

const _unitOffset = 0.05;

const _processLimit = 20.0;
const _bulletSpeed = 0.22;
const _enhanceBulletSpeed = 0.08;
const _smallEnemySpeed = 1.0;
const _middleEnemySpeed = 3.0;
const _largeEnemySpeed = 10.0;
const _supplySpeed = 30.0;

Timer _timer(double limit, foundation.VoidCallback? onTick) {
  return Timer(
    math.max(limit, _unitOffset),
    repeat: true,
    autoStart: false,
    onTick: onTick,
  );
}

/// Timers状态
enum TimersState {
  /// 闲置
  idle,

  /// 开始
  started,

  /// 暂停
  paused,

  /// 停止
  stopped,
}

/// Created by changlei on 2022/5/20.
///
/// 计时器
class Timers {
  /// 计时器
  Timers({
    this.bulletBuilder,
    this.enemyBuilder,
    this.supplyBuilder,
    this.onSpeedUp,
  }) {
    _buildTimers();
  }

  /// 构建子弹
  final foundation.VoidCallback? bulletBuilder;

  /// 构建敌机
  final foundation.ValueChanged<EnemyType>? enemyBuilder;

  /// 构建奖励
  final foundation.VoidCallback? supplyBuilder;

  /// 加速
  final foundation.ValueChanged<double>? onSpeedUp;

  late final _processTimer = _timer(_processLimit, _onProcessTick);

  Timer? _bulletTimer;
  Timer? _supplyTimer;

  late Timer _smallEnemyTimer;
  late Timer _middleEnemyTimer;
  late Timer _largeEnemyTimer;

  late TimersState _state = TimersState.idle;

  late double _smallEnemyLimit = _smallEnemySpeed;
  late double _middleEnemyLimit = _middleEnemySpeed;
  late double _largeEnemyLimit = _largeEnemySpeed;

  double _offset = 0.0;

  /// 当前增速
  double get offset => _offset;

  /// 增加子弹生产速度
  void speedUpBullet() {
    if (_bulletTimer?.limit == _enhanceBulletSpeed) {
      return;
    }
    _bulletTimer?.stop();
    _bulletTimer = _timer(_enhanceBulletSpeed, bulletBuilder);
    _bulletTimer?.start();
  }

  /// 减缓子弹生产速度
  void speedDownBullet() {
    if (_bulletTimer?.limit == _bulletSpeed) {
      return;
    }
    _bulletTimer?.stop();
    _bulletTimer = _timer(_bulletSpeed, bulletBuilder);
    _bulletTimer?.start();
  }

  void _onProcessTick() {
    _speedUp(_unitOffset);
  }

  void _buildTimers() {
    _bulletTimer ??= _timer(_bulletSpeed, bulletBuilder);
    _supplyTimer ??= _timer(_supplySpeed, supplyBuilder);
    _smallEnemyTimer = _timer(_smallEnemyLimit, () => enemyBuilder?.call(EnemyType.small));
    _middleEnemyTimer = _timer(_middleEnemyLimit, () => enemyBuilder?.call(EnemyType.middle));
    _largeEnemyTimer = _timer(_largeEnemyLimit, () => enemyBuilder?.call(EnemyType.large));
  }

  void _speedUp(double offset) {
    _offset += offset;
    onSpeedUp?.call(offset);
    _smallEnemyLimit -= offset;
    _middleEnemyLimit -= offset;
    _largeEnemyLimit -= offset;
    _smallEnemyTimer.stop();
    _middleEnemyTimer.stop();
    _largeEnemyTimer.stop();
    _buildTimers();
    _restoreState();
  }

  void _restoreState() {
    switch (_state) {
      case TimersState.idle:
        reset();
        break;
      case TimersState.started:
        start();
        break;
      case TimersState.paused:
        pause();
        break;
      case TimersState.stopped:
        stop();
        break;
    }
  }

  /// 重置
  void reset() {
    _state = TimersState.idle;
    _processTimer.reset();
    _bulletTimer?.reset();
    _supplyTimer?.reset();
    _smallEnemyTimer.reset();
    _middleEnemyTimer.reset();
    _largeEnemyTimer.reset();
    _smallEnemyLimit = _smallEnemySpeed;
    _middleEnemyLimit = _middleEnemySpeed;
    _largeEnemyLimit = _largeEnemySpeed;
    _buildTimers();
    _offset = 0.0;
  }

  /// 开始
  void start() {
    _state = TimersState.started;
    if (_processTimer.current == 0) {
      _processTimer.start();
    } else {
      _processTimer.resume();
    }
    if (_bulletTimer?.current == 0) {
      _bulletTimer?.start();
    } else {
      _bulletTimer?.resume();
    }
    if (_supplyTimer?.current == 0) {
      _supplyTimer?.start();
    } else {
      _supplyTimer?.resume();
    }
    if (_smallEnemyTimer.current == 0) {
      _smallEnemyTimer.start();
    } else {
      _smallEnemyTimer.resume();
    }
    if (_middleEnemyTimer.current == 0) {
      _middleEnemyTimer.start();
    } else {
      _middleEnemyTimer.resume();
    }
    if (_largeEnemyTimer.current == 0) {
      _largeEnemyTimer.start();
    } else {
      _largeEnemyTimer.resume();
    }
  }

  /// 暂停
  void pause() {
    _state = TimersState.paused;
    _processTimer.pause();
    _bulletTimer?.pause();
    _supplyTimer?.pause();
    _smallEnemyTimer.pause();
    _middleEnemyTimer.pause();
    _largeEnemyTimer.pause();
  }

  /// 停止
  void stop() {
    _state = TimersState.stopped;
    _processTimer.stop();
    _bulletTimer?.stop();
    _supplyTimer?.stop();
    _smallEnemyTimer.stop();
    _middleEnemyTimer.stop();
    _largeEnemyTimer.stop();
    _smallEnemyLimit = _smallEnemySpeed;
    _middleEnemyLimit = _middleEnemySpeed;
    _largeEnemyLimit = _largeEnemySpeed;
    _buildTimers();
    _offset = 0.0;
  }

  /// 更新
  void update(double dt) {
    _processTimer.update(dt);
    _bulletTimer?.update(dt);
    _supplyTimer?.update(dt);
    _smallEnemyTimer.update(dt);
    _middleEnemyTimer.update(dt);
    _largeEnemyTimer.update(dt);
  }
}
